use unistd::*;

use x86_64::{PhysAddr, VirtAddr};

pub fn alloc_dma(size: usize) -> usize {
    enter_syscall(size, 0, 0, 0, 0, 0, SYS_ALLOC_DMA)
}

pub fn free_dma(addr: usize, size: usize) {
    enter_syscall(addr, size, 0, 0, 0, 0, SYS_FREE_DMA);
}

pub struct DmaManager;

impl DmaManager {
    pub const UNIT_SIZE: usize = 4096;

    pub fn allocate(size: usize) -> (PhysAddr, VirtAddr) {
        let count = size.div_ceil(Self::UNIT_SIZE);

        let address = alloc_dma(count);
        unistd::mm::mmap(address, size, 0, 0x7);
        let physical_address = PhysAddr::new(address as u64);
        let virtual_address = VirtAddr::new(address as u64);
        (physical_address, virtual_address)
    }

    pub fn deallocate(virtual_address: VirtAddr) {
        free_dma(virtual_address.as_u64() as usize, 1);
    }
}
